#!/bin/sh

DIR=`pwd`
BINDIR="$DIR/bin"
INDIR="$DIR/in"
OUTDIR="$DIR/out"

BIN_TIME="/usr/bin/time"

# default values
TIMELIMIT=30     # time limit (seconds)
MEMLIMIT=32768   # memory limit (kb) (stack memory limit is equal)
SRCLIMIT=100     # src file size limit (kb)
EXELIMIT=5120    # binary file size limit (kb)

if [ -f "$DIR/spr.conf" ] ; then . "$DIR/spr.conf" ; fi

export EXELIMIT SRCLIMIT

TASK="$1"

if [ "$TYPE" == "icm" ]
then OPT="quiet"
    TASKS=$TASKS_ICM
fi
if [ "$QUIET" == "yes" ]; then OPT="quiet"; fi

CHECKER=$BIN_COMPARE

EXIT_NORMAL=0
EXIT_RTE=1
EXIT_MLE=2
EXIT_TLE=3
EXIT_ILLEGAL=8
EXIT_CHECKER=9

STATUS_NOTCHECKED=0
STATUS_ACCEPT=1
STATUS_WRONGSOLUTION=2
STATUS_INTERNAL=3
STATUS_CONF=4

function error() {
    echo $2 >status
    echo "ERROR: $1"
    exit 1
}

function prepare() {
    if [ -z "`echo "$TASKS" | grep "$TASK"`" ]
    then
        error "Unknown task: $TASK" $STATUS_CONF
    fi

    FOUND=0
    for EXT in c cpp
    do   #get extension
        if [ -f "$TASK.$EXT" ]
        then
            FOUND=1
            break
        fi
    done

    if [ $FOUND -eq 0 ]
    then
        error "No solution: $TASK" $STATUS_INTERNAL
    fi

    if ! $BINDIR/compile $TASK.$EXT
    then
        error "Compilation error" $STATUS_WRONGSOLUTION
    fi
    SOL="${TASK}.e"

    if [ -f "$BINDIR/${TASK}chk.e" ]
    then
        CHECKER="$BINDIR/${TASK}chk.e"
    else CHECKER="$BINDIR/compare"
    fi
}

function check() {
    IN="$INDIR/$TASK$TEST.in"
    OUT="$OUTDIR/$TASK$TEST.out"
    TMP="$TASK.out"

    rm -f "$TMP"

    if [ -n "$TEST" ] ; then
        if [ ! -f "$IN" ] ; then
            error "No file: ${TASK}${TEST}.in" $STATUS_WRONGSOLUTION
        fi

        if [ ! -f "$OUT" ] ; then
            error "No file: ${TASK}${TEST}.out" $STATUS_WRONGSOLUTION
        fi
    fi

    echo -n "Test $TEST --"

    if [ "`eval echo '$TIMELIMIT_'${TASK}`" = "" ]
    then TIMELIMIT_TASK=$TIMELIMIT
    else TIMELIMIT_TASK=`eval echo '$TIMELIMIT_'${TASK}`
    fi

    if [ "`eval echo '$MEMLIMIT_'${TASK}`" = "" ]
    then MEMLIMIT_TASK=$MEMLIMIT
    else MEMLIMIT_TASK=`eval echo '$MEMLIMIT_'${TASK}`
    fi

    TMP_FILE="/tmp/tmpfile.$$"
    (ulimit -t $((TIMELIMIT_TASK-1)) -v $MEMLIMIT_TASK -s $MEMLIMIT_TASK; $BIN_TIME -f "%U" -o $TMP_FILE $BINDIR/secure $SOL < $IN > $TMP )
    RUN_RES=$?
    killall -9 $SOL 2>/dev/null

    TIME_RES=`tail -1 "$TMP_FILE"`
    rm -f "$TMP_FILE"

    echo -n "$TIME_RES "
    TST_RES="???"
    CHK_TXT=""
    if [ $RUN_RES -eq $EXIT_NORMAL ]
    then
        if [ -f "$OUT" ]
        then
            $CHECKER "$TMP" "$OUT" "$IN" > $TMP_FILE

            CHK_RES=`head -1 $TMP_FILE`
            CHK_TXT=`tail -1 $TMP_FILE`
            rm -f "$TMP_FILE"

            if [ "$CHK_RES" = "OK" ]
            then
                TST_RES="OK"
            else
                echo $STATUS_WRONGSOLUTION >status
                TST_RES="WRONG ANSWER"
            fi
        else
            echo $STATUS_WRONGSOLUTION >status
            TST_RES="NO ANSWER"
        fi
    elif [ $RUN_RES -eq $EXIT_TLE ]
    then
        echo $STATUS_WRONGSOLUTION >status
        TST_RES="TIME LIMIT EXCEEDED"
    elif [ $RUN_RES -eq $EXIT_MLE ]
    then
        echo $STATUS_WRONGSOLUTION >status
        TST_RES="MEMORY LIMIT EXCEEDED"
    elif [ $RUN_RES -eq $EXIT_RTE ]
    then
        echo $STATUS_WRONGSOLUTION >status
        TST_RES="RUN TIME ERROR"
    elif [ $RUN_RES -eq $EXIT_ILLEGAL ]
    then
        echo $STATUS_WRONGSOLUTION >status
        TST_RES="FORBIDDEN FUNCTION"
    elif [ $RUN_RES -eq $EXIT_CHECKER ]
    then
        echo $STATUS_INTERNAL >status
        TST_RES="INTERNAL CHECKER ERROR"
    fi

    echo "$TST_RES"
    if [ "$OPT" != "quiet" ]
    then
        if [ -n "$CHK_TXT" -a "$TST_RES" != "OK" ]
        then
            echo "     >> $CHK_TXT"
        fi
    fi
}

prepare
echo "---"
for TEST in `eval echo '$TESTS_'${TASK}`
do
    check
done
echo $STATUS_ACCEPT >>status
